#!/usr/bin/python
"""
Main executable for the Minigame Mayhem game.

"""

#  Copyright 2010 Nick Ryder.

#  This file is part of Minigame Mayhem.

#  Minigame Mayhem is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.

#  Minigame Mayhem is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.

#  You should have received a copy of the GNU General Public License
#  along with Minigame Mayhem.  If not, see <http://www.gnu.org/licenses/>.

import sys, os
import pygame
from pygame.locals import *
import time
cwd = os.getcwd()
minigamepath = os.path.split(cwd)[0]
minigamepath = os.path.join(minigamepath, "minigames")
sys.path.append(minigamepath)
import testminigame
import pairsminigame

class MinigameMayhem:
   "Main class for Minigame Mayhem game."

   def __init__(self):
      self.mode = None     # String: mode [exit, play, rename].
      self.username = None # String: name of player.
      self.lives = 5       # Int: Number of lives remaining.
      self.level = 1       # Int: Difficulty level.
      self.score = 0       # Int: number of games won.
      self.minigames = []  # List: minigame classes.
      self.loadGames()
      # Need to tidy up and learn to use pygame well again.
      self.backgroundcolour = (0, 50, 0) 
      pygame.init()
      self.screen = pygame.display.set_mode((800, 600))
      pygame.display.set_caption("Minigame Mayhem")
      self.background = pygame.Surface(self.screen.get_size())
      self.background.convert()
      self.background.fill(self.backgroundcolour)
      self.screen.blit(self.background, (0, 0))
      pygame.display.flip()
      self.titlescreen()

   def titlescreen(self):
      "Displays the game title and license info."
      title = "Minigame Mayhem!"
      copyright = "Minigame Mayhem Copyright 2010 Nick Ryder."
      warranty = "This program comes with ABSOLUTELY NO WARRANTY."
      license0 = "This is free software, released under the"
      license1 = "GNU General Public License Version 3."
      self.background.fill(self.backgroundcolour)
      self.screen.blit(self.background, (0, 0))
      titleFont = pygame.font.Font(None, 50)
      infoFont = pygame.font.Font(None, 20)
      title = titleFont.render(title, 1, (0, 0, 100))
      titlepos = title.get_rect(centerx=self.background.get_width()/2, 
         centery=self.background.get_height()/2)
      self.background.blit(title, titlepos)
      copyright = infoFont.render(copyright, 1, (0, 0, 0))
      warranty = infoFont.render(warranty, 1, (0, 0, 0))
      license0 = infoFont.render(license0, 1, (0, 0, 0))
      license1 = infoFont.render(license1, 1, (0, 0, 0))
      copyrightpos = copyright.get_rect(centerx=self.background.get_width()/2,
         midtop=titlepos.midbottom)
      copyrightpos.move(0, 20)
      warrantypos = warranty.get_rect(centerx=self.background.get_width()/2,
         midtop=copyrightpos.midbottom)
      license0pos = license0.get_rect(centerx=self.background.get_width()/2,
         midtop=warrantypos.midbottom)
      license1pos = license1.get_rect(centerx=self.background.get_width()/2,
         midtop=license0pos.midbottom)
      self.background.blit(copyright, copyrightpos)
      self.background.blit(warranty, warrantypos)
      self.background.blit(license0, license0pos)
      self.background.blit(license1, license1pos)
      self.screen.blit(self.background, (0, 0))
      pygame.display.flip()
      time.sleep(5)
      

   def welcome(self):
      "A welcome screen displayed at the beginning of the game."
      if self.username != None:
         message = "Welcome to Minigame Mayhem %s!" % self.username
      else:
         message = "Welcome to Minigame Mayhem!"
      print message
      font = pygame.font.Font(None, 36)
      text = font.render(message, 1, (10, 10, 10))
      self.background = pygame.Surface(self.screen.get_size())
      self.background.convert()
      self.background.fill(self.backgroundcolour)
      textpos = text.get_rect(centerx=self.background.get_width()/2)
      self.background.blit(text, textpos)
      textpos = textpos.move(0, textpos.height)
      self.background.blit(text, textpos)
      self.screen.blit(self.background, (0, 0))
      pygame.display.flip()

   def menu(self):
      "A menu where the user selects what to do."
      self.background.fill(self.backgroundcolour)
      fontTitle = pygame.font.Font(None, 36)
      fontButton = pygame.font.Font(None, 20)
      option1 = "Play Games"
      option2 = "Change Name"
      option3 = "Delete Data"
      option4 = "Exit"
      options = [option1, option2, option3, option4]
      buttonsize = fontButton.size(option1)
      for count in range(1, len(options)):
         size = fontButton.size(options[count])
         if size > buttonsize:
            buttonsize = size
      button = pygame.Surface(buttonsize)
      button.convert()
      buttonrects = []
      for count in range(len(options)):
         option = options[count]
         option = fontButton.render(option, 1, (0, 0, 0))
         button.fill((0, 0, 150))
         buttonrect = button.get_rect()
         buttonrect.centerx = self.background.get_width()/2
         buttonrect.centery = 50 * (count + 1)
         buttonrects.append(buttonrect)
         textrect = option.get_rect()
         textrect.centerx = buttonrect.width/2
         button.blit(option, textrect)
         self.background.blit(button, buttonrect)
      self.screen.blit(self.background, (0,0))
      pygame.display.flip()
      selectionMade = False
      while not selectionMade:
         for event in pygame.event.get():
            if event.type == QUIT:
               self.mode = "exit"
               selectionMade = True
            elif event.type == KEYDOWN:
               if event.key == K_ESCAPE:
                  self.mode = "exit"
                  selectionMade = True
            elif event.type == MOUSEBUTTONDOWN:
               x, y = pygame.mouse.get_pos()
               if buttonrects[0].collidepoint(x, y):
                  self.mode = "play"
                  selectionMade = True
               elif buttonrects[1].collidepoint(x, y):
                  self.mode = "rename"
                  selectionMade = True
               elif buttonrects[2].collidepoint(x, y):
                  self.mode = "clearData"
                  selectionMade = True
               elif buttonrects[3].collidepoint(x, y):
                  self.mode = "exit"
                  selectionMade = True

   def highScores(self):
      "The high scores are displayed and saved."
      filename = os.path.join("data", "scores")
      scores = []
      try:
         inp = open(filename, "r")
         for line in inp:
            line = line.split(":")
            if len(line) == 2:
               score = []
               score.append(line[0].rstrip())     # Get username.
               try:
                  score.append(int(line[1])) # Get score.
                  scores.append(score)
               except ValueError:
                  print "Found error in score."
            else:
               print "Found bad line in high scores."
         inp.close()
      except:
         pass
      addAt = None
      for count in range(len(scores)):
         if self.score > scores[count][1] and addAt == None:
            addAt = count
      score = [self.username, self.score]
      if addAt != None:
         scores.insert(addAt, score)
      if len(scores) < 5 and addAt == None:
         scores.append(score)
      outp = open(filename, "w")
      if len(scores) > 4:
         max = 5
      else:
         max = len(scores)
      for score in scores[:max]:
         outp.write("%s: %d\n" % (score[0], score[1]))
      outp.close()
      self.background.fill(self.backgroundcolour)
      font = pygame.font.Font(None, 30)
      scoretitle = "High Scores:"
      title = font.render(scoretitle, 1, (0, 0, 0))
      titlerect = title.get_rect(centerx = self.background.get_width()/2,
         centery = 50)
      self.background.blit(title, titlerect)
      for count in range(len(scores)):
         datum = font.render("%d) %s : %s" % (count + 1, scores[count][0],
            scores[count][1]), 1, (0, 0, 0))
         datumrect = datum.get_rect(centerx = self.background.get_width()/2,
            centery = 50 * (count + 2))
         self.background.blit(datum, datumrect)
      self.screen.blit(self.background, (0, 0))
      pygame.display.flip()
      time.sleep(2)
      
   def setUsername(self):
      "The user enters their name to be used in high scores."
      self.background.fill(self.backgroundcolour)
      titleFont = pygame.font.Font(None, 36)
      nameFont = pygame.font.Font(None, 25)
      title = titleFont.render("Enter name:", 1, (0, 0, 0))
      titlerect = title.get_rect(centerx = self.background.get_width()/2,
         centery = 50)
      self.background.blit(title, titlerect)
      self.screen.blit(self.background, (0,0))
      pygame.display.flip()
      nameFont = pygame.font.Font(None, 30)
      finished = False
      username = ""
      while not finished:
         for event in pygame.event.get():
            if event.type == QUIT:
               self.mode = "exit"
               finished = True
            if event.type == KEYDOWN:
               if event.key == K_RETURN:
                  finished = True
               elif event.key == K_DELETE or event.key == K_BACKSPACE:
                  if len(username) > 0:
                     username = username[:-1]
               else:
                  username += event.unicode
         name = nameFont.render(username, 1, (0, 0, 0))
         namerect = name.get_rect(centerx = self.background.get_width()/2,
            centery = self.background.get_width()/2)
         self.background.fill(self.backgroundcolour)
         self.background.blit(title, titlerect)
         self.background.blit(name, namerect)
         self.screen.blit(self.background, (0, 0))
         pygame.display.flip()
      self.username = username

   def play(self):
      "The main loop where the user plays games."
      self.lives = 5
      self.level = 1
      self.score = 0
      while self.lives > 0:
         game = self.minigames[1](self.screen, self.level)
         game.run()
         if game.win == True:
            self.score += 1
            if self.score == 2 ** (self.level + 1):
               self.level += 1
         else:
            self.lives -= 1
         self.printScore()
      self.background.fill(self.backgroundcolour)
      font = pygame.font.Font(None, 50)
      gameover = font.render("Game Over.", 1, (0, 0, 0))
      gameoverrect = gameover.get_rect(centerx=self.background.get_width()/2, 
         centery=self.background.get_height()/2)
      self.background.blit(gameover, gameoverrect)
      self.screen.blit(self.background, (0, 0))
      pygame.display.flip()
      time.sleep(2)
      self.highScores()

   def printScore(self):
      "Print score, level and number of lives remaining."
      self.background.fill(self.backgroundcolour)
      font = pygame.font.Font(None, 30)
      score = "Score: %d" % self.score
      lives = "Lives: %d" % self.lives
      level = "Level: %d" % self.level
      data = [score, lives, level]
      for count in range(len(data)):
         datum = font.render(data[count], 1, (0, 0, 0))
         datumrect = datum.get_rect(centerx = self.background.get_width()/2,
            centery = 50 * (count + 1))
         self.background.blit(datum, datumrect)
      self.screen.blit(self.background, (0, 0))
      pygame.display.flip()
      time.sleep(2)
      pass

   def exit(self):
      "An exit screen displayed at the end of the game."
      credits = "Credits:"
      devmsg = "Developers:"
      testmsg = "Testers:"
      artmsg = "Artists:"
      developers = []
      testers = []
      artists = []
      for game in self.minigames:
         game = game(self.screen, 0)
         for dev in game.developers:
            if dev not in developers:
               developers.append(dev)
         for artist in game.artists:
            if artist not in artists:
               artists.append(artist)
         for tester in game.testers:
            if tester not in testers:
               testers.append(tester)
      devmsg1 =""
      for developer in developers:
         devmsg1 += developer + ", "
      artmsg1 = ""
      for artist in artists:
         artmsg1 += artist + ", "
      testmsg1 = ""
      for tester in testers:
         testmsg1 += tester + ", "
      if len(devmsg1) > 0:
         devmsg1 = devmsg1[:-2]
      if len(artmsg1) > 0:
         artmsg1 = artmsg1[:-2]
      if len(testmsg1) > 0:
         testmsg1 = testmsg1[:-2]
      self.background = pygame.Surface(self.screen.get_size())
      self.background.convert()
      self.background.fill(self.backgroundcolour)
      fontTitle = pygame.font.Font(None, 36)
      fontSubTitle = pygame.font.Font(None, 30)
      fontInfo = pygame.font.Font(None, 26)
      title = fontTitle.render(credits, 1, (0, 0, 0))
      textpos = title.get_rect(centerx=self.background.get_width()/2, 
         top = 40)
      self.background.blit(title, textpos)
      devstext = fontSubTitle.render(devmsg, 1, (0, 0, 0))
      textpos = devstext.get_rect(centerx=self.background.get_width()/2,
         midtop=textpos.midbottom)
      self.background.blit(devstext, textpos)
      devstext1 = fontSubTitle.render(devmsg1, 1, (0, 0, 0))
      textpos = devstext1.get_rect(centerx=self.background.get_width()/2,
         midtop=textpos.midbottom)
      self.background.blit(devstext1, textpos)
      arttext = fontSubTitle.render(artmsg, 1, (0, 0, 0))
      textpos = arttext.get_rect(centerx=self.background.get_width()/2,
         midtop=textpos.midbottom)
      self.background.blit(arttext, textpos)
      arttext1 = fontSubTitle.render(artmsg1, 1, (0, 0, 0))
      textpos = arttext1.get_rect(centerx=self.background.get_width()/2,
         midtop=textpos.midbottom)
      self.background.blit(arttext1, textpos)
      testtext = fontSubTitle.render(testmsg, 1, (0, 0, 0))
      textpos = testtext.get_rect(centerx=self.background.get_width()/2,
         midtop=textpos.midbottom)
      self.background.blit(testtext, textpos)
      testtext1 = fontSubTitle.render(testmsg1, 1, (0, 0, 0))
      textpos = testtext1.get_rect(centerx=self.background.get_width()/2,
         midtop=textpos.midbottom)
      self.background.blit(testtext1, textpos)
      
      self.screen.blit(self.background, (0, 0))
      pygame.display.flip()
      time.sleep(3)

   def loadGames(self):
      "Get minigame classes and list in self.minigames."
      self.minigames.append(pairsminigame.PairsMinigame)
      self.minigames.append(testminigame.TestMinigame)

   def resetScores(self):
      "Reset the high scores."
      filename = os.path.join("data", "scores")
      outp = open(filename, "w")
      outp.close()
      self.background.fill(self.backgroundcolour)
      font = pygame.font.Font(None, 30)
      text = font.render("Data deleted.", 1, (0, 0, 0))
      textrect = text.get_rect(centerx = self.background.get_width()/2,
         centery = self.background.get_height()/2)
      self.background.blit(text, textrect)
      self.screen.blit(self.background, (0, 0))
      pygame.display.flip()
      time.sleep(1)

if __name__ == "__main__":
   mm = MinigameMayhem()
   mm.setUsername()
   while mm.mode != "exit":
      mm.menu()
      if mm.mode == "play":
         mm.play()
      elif mm.mode == "rename":
         mm.setUsername()
      elif mm.mode == "clearData":
         mm.resetScores()
   mm.exit()
